跳到主要内容

VideoPlayer 视频播放器

介绍

  • 支持横竖屏布局与组件级全屏(不打断播放进度)
  • 长按倍速播放以及长按下拉倍速锁定 (长按触发倍速播放,长按下拉触发倍速锁)
  • 沉浸式模式(双指捏合进入/退出,隐藏控件/进度条/弹幕)
  • 自定义控制条(按钮显隐、插槽扩展、自定义渲染)
  • 进度条预览(分片小窗、时间范围提示、实时时间)
  • 拖拽小窗分片预览能力 (拖拽进度条能实时显示当前视频的切片)
  • 上次观看记录(10%~90% 区间节流存储,自动恢复并气泡提示)
  • 弹幕能力(顶/中/底三栏,密度/速度可配,随倍速/播放状态同步,可动态发送)
  • 震动反馈(捏合/长按倍速进入与恢复的轻/重震)

安装与引入

import FQVideoPlayer from '@fq/fq-weapp-ui-pro';

按需样式(按需引入时需要):

import '@fq/fq-weapp-ui-pro/dist/styles/components/video-player.scss';

基础用法

<FQVideoPlayer
loop
autoplay
src="https://ifengqun.oss-cn-shenzhen.aliyuncs.com/uploadtest/0-lxtzk7yj0jm.mp4"
cover="https://applet.ifengqun.com/fq-mall/snapshot/115_first_frame.jpg"
/>

横屏模式 + 组件级全屏

<FQVideoPlayer
src="..."
cover="..."
// 横屏时才展示全屏按钮;进入全屏时 UI 方向切到 Portrait(不影响播放)
controls={{ buttons: { fullScreen: true } }}
/>

进度条预览(小窗 + 时间范围)

<FQVideoPlayer
src="..."
slider={{
size: 'middle',
showTimeRange: true,
enablePreview: true,
previewOptions: [
{ snapshot: 'https://.../output_01.jpg', time: 0 },
{ snapshot: 'https://.../output_02.jpg', time: 14 },
// ...
],
}}
/>

自定义控制条(扩展按钮 / 完全自定义)

const extraButtons = [
<View key="collect" onClick={() => console.log('collect')}>收藏</View>,
<View key="download" onClick={() => console.log('download')}>下载</View>,
];

<FQVideoPlayer
src="..."
controls={{
buttons: { menu: true, play: true, mute: true, rate: true, fullScreen: true },
extraButtons,
// 或者完全自定义:renderButtons: (ctx) => (<View>...</View>)
}}
/>

上次观看(自动记录/恢复)

<FQVideoPlayer
src="..."
lastWatch={{
throttleMs: 4000,
minResumeSec: 5,
ignoreTailSec: 2,
startPercent: 10,
endPercent: 90,
}}
/>

手势与沉浸式

<FQVideoPlayer
src="..."
enablePinchGesture // 默认 true:外捏进入沉浸式,内捏退出
// immersive 也可受控传入(true/false)
/>

弹幕(静态 + 动态发送)

const ref = useRef<any>(null);

<FQVideoPlayer
ref={ref}
src="..."
barrage={{
enabled: true,
density: { top: 2, middle: 3, bottom: 2 },
data: [
{ id: 1, text: 'Hello!', time: 1, zone: 'top' },
{ id: 2, text: '支持倍速/暂停同步', time: 3, zone: 'middle' },
],
}}
/>

// 运行时发送
ref.current?.sendBarrage?.({ text: '这是一条新弹幕' });

API

FQVideoPlayer Props

参数名类型默认值说明
widthnumber-组件宽(用于方向预判,可选)
heightnumber-组件高(用于方向预判,可选)
srcstring必填视频地址
coverstring-自定义封面(组件层渲染,支持 coverFit
coverFit'cover' | 'contain'contain封面适配方式
mutedbooleanfalse静音
controlsboolean | ControlsOptionstrue控制条:false 隐藏;对象启用自定义按钮与插槽
autoplaybooleanfalse自动播放
loopbooleanfalse循环播放;同时驱动弹幕循环
initialTimenumber0初始起播秒数(不自动播放时仅 seek,不播放)
objectFit'contain' | 'fill' | 'cover'contain视频铺放模式
classNamestring-容器类名
stylesFQVideoPlayerStyles-统一样式(root/movableArea/movableView/video/bar/controls/cover
barrageboolean | BarrageOptionsfalse弹幕开关/配置(true 使用默认)
showSliderRealtimeInfobooleantrue进度条两侧实时时间(左:当前,右:剩余)
sliderboolean | SliderOptionstrue进度条开关与配置(对象时需提供 size
orientationOrientationautoauto/portrait/landscape(内部自动/强制方向)
layoutPreset'default' | 'compact' | 'spacious'default预留布局预设
enableProgressGesturebooleanfalse是否开启进度滑动手势(保留)
enablePinchGesturebooleantrue是否开启双指捏合沉浸式切换
lastWatchboolean | LastWatchOptionsfalse上次观看:开关/配置
onCloseFunction: void-关闭按钮回调:竖屏全屏视频场景向外层触发
onPlayFunction: void-播放事件
onPauseFunction: void-暂停事件
onEndedFunction: void-结束事件(会清理 lastWatch 缓存)
onError(err: ErrorMsg) => void-统一错误(结构化 ErrorMsg
onTimeUpdateFunction: void-进度更新
onWaitingFunction: void-缓冲中
onLoadedMetadataFunction: void-元数据就绪(内部会做方向与初始进度同步)
onOrientationChange(o: Orientation) => void-布局方向变化回调
onPreloadNextVideo(id: string) => void-缓冲>10% 时触发预加载下一段
onPlayBackRate(rate: number, type: 'manual' | 'touch') => void-倍速变更回调
onScaleChange(isScale: boolean) => void-缩放进入/退出状态(沉浸式手势)
onDoubleTap(e) => void-双击事件
videoIdstring-自定义视频实例标识(选择器)
pageIdstring | number-页面标识(事件总线隔离)

ControlsOptions

属性类型默认值说明
renderLeftReact.ReactNode默认关闭按钮左侧区域插槽(竖屏时展示,横屏隐藏)。返回节点替换默认关闭按钮。
renderExtraRightReact.ReactNode-最右侧额外区域插槽。
buttons{ menu?: boolean; play?: boolean; mute?: boolean; rate?: boolean; fullScreen?: boolean; }{ menu:true, play:true, mute:true, rate:true, fullScreen:false }基础按钮显隐配置。全屏按钮需显式开启。
extraButtonsReact.ReactNode[][]自定义按钮数组,插入在内置按钮之后,支持直接传节点。非法子类型(对象/函数/布尔)会被安全忽略。
renderButtons`React.ReactNode(ctx) => React.ReactNode`-

子项:buttons

类型默认值说明
menubooleantrue显示“更多/菜单”按钮
playbooleantrue显示“播放/暂停”按钮
mutebooleantrue显示“静音/取消静音”按钮
ratebooleantrue显示“倍速”按钮(循环 0.5x→1x→1.25x→1.5x→2x)
fullScreenbooleanfalse显示“全屏”按钮(仅横屏布局生效)

提示:全屏按钮仅在横屏布局下展示有效(内部已有 isLandscape 判断),且需 fullScreen: true

SliderOptions

属性类型默认值说明
size'large' | 'middle' | 'small'必填进度条尺寸。
showRealtimeTimeInfobooleantrue是否在进度条两侧显示实时时间(左:当前,右:剩余)。
showTimeRangebooleantrue拖拽中是否在顶部显示 time-range 提示文本。
enablePreviewbooleanfalse是否启用拖拽预览小窗(若同时使用旧 props enablePreviewSnapshots 也会启用)。
previewOptions{ snapshot: string; time: number }[]-预览分片配置,time 为该切片代表的出现秒数。
previewThrottleMsnumber200预览小窗图片更新的节流间隔(毫秒)。
styles{ wrapper?; track?; buffer?; handle?; realtime? }-进度条各部件的内联样式定制。

说明:横屏时预览小窗按 16:9 呈现,竖屏按 9:16 呈现。

LastWatchOptions

属性类型默认值说明
throttleMsnumber4000节流写入本地缓存的最小间隔(毫秒)。
minResumeSecnumber5最小可恢复的播放秒数(不足不记录)。
ignoreTailSecnumber2距离视频结尾的忽略秒数(过近不恢复)。
startPercentnumber10参与记录/恢复的起始百分比(含)。
endPercentnumber90参与记录/恢复的结束百分比(含)。

策略:仅在区间内(10%~90%)且间隔到达节流阈值时写入;超出区间或播放结束会清理缓存。

BarrageOptions(弹幕)

属性类型默认值说明
enabledbooleanfalse是否启用弹幕显示。
density{ top?: number; middle?: number; bottom?: number }-顶/中/底三区各自的行数(密度)。
speedPxPerSecnumber-基础速度(px/s),会随 playbackRate 同步变更。
dataBarrageItem[]-静态数据源,BarrageItem 包含 id/text/avatar?/zone?/time。未提供 zone 时内部会稳定分配车道。
stylesReact.CSSProperties-弹幕容器样式。
classNamestring-弹幕容器自定义类名。

BarrageItem 结构:{ id: string|number; text: string; avatar?: string; zone?: 'top'|'middle'|'bottom'; time: number }

Ref 能力(FQVideoPlayerRef)

方法签名说明
play(): Promise<void>播放。
pause(): Promise<void>暂停。
seek(time: number): Promise<void>跳转到指定秒。
setPlaybackRate(rate: number): Promise<void>设置倍速,手动来源会重置锁条与锁定态。
mute(): void静音。
unmute(): void取消静音。
setMuted(muted: boolean): void显式设置静音开关。
enterFullscreen(): void组件级全屏(仅横屏布局下进入;已全屏则无效)。
exitFullscreen(): void退出组件级全屏。
toggleFullscreen(): void切换组件级全屏(横屏进入/退出)。
sendBarrageBarrageItem发送一条新弹幕,立即出现在当前时间窗口。
getState(): { playing; loading; muted; playbackRate; immersive; currentTimeSeconds; totalDurationSeconds; bufferPercent; orientation; isFullscreen; }获取当前内部状态快照。

常见问题

  • 全屏按钮为什么不显示?
    • 需设置 controls.buttons.fullScreen = true,且仅在横屏布局下显示。
  • 预览小窗横屏显示有白边?
    • 已在横屏使用 16:9 尺寸,竖屏 9:16;请确保传入的切片图本身也是对应比例。
  • 上次观看为何未恢复?
    • 小于 startPercent 或超过 endPercent(或接近结尾 ignoreTailSec)不会恢复;首次播放不足 minResumeSec 也不会记录。